// 该文件中的代码是添加到HTML中通过浏览器执行的

// 定义一个用来根据CSS选择器选择单个DOM元素的函数
const $ = selector => document.querySelector( selector );

/**
 * 采用XMLHttpReqeust封装一个用来发送异步请求的函数
 * @param {string} method 表示请求方式
 * @param {string} url 表示请求路径
 * @param {string|object} data 向服务端发送的数据
 * @param {function} success 表示"请求-响应"成功后的回调函数
 * @param {string|object} headers 请求头
 */
const ajax = (method, url, data, success, headers) => {
    // 1、创建用来发送请求、接收响应的对象
    let $http = new XMLHttpRequest();

    if( success && typeof success === 'function' ){
        // 2、绑定监听器，用于监听 readyState 属性值的变化
        $http.addEventListener( 'readystatechange' , () => {
            // 当响应结束时
            if( $http.readyState === $http.DONE ) {
                // 就调用 success 函数并将 响应数据 和 $http 作为参数传递过去
                success( $http.response , $http );
            }
        } , false );
    }

    // 3、打开连接
    $http.open( method , url );

    // 4、设置请求头
    if( headers ){
        // 若 headers 为 string 则认为是在设置 content-type
        if( typeof headers === 'string' ) {
            // 因此将 headers 中的字符串当作 content-type 取值来对待
            let contentType = headers ;
            // 设置请求头
            $http.setRequestHeader( 'content-type' , contentType );
        }
        // 若 headers 为 对象则认为其中包含多项请求头
        if( typeof headers === 'object' ) {
            let names = Object.getOwnPropertyNames( headers );
            names.forEach( name => {
                let value = headers[ name ];
                $http.setRequestHeader( name , value );
            });
        }
    }

    // 5、发送请求
    $http.send( data );
}

// 选择页面上的元素
const editor = $('.editor');
const accountInput = editor.querySelector( 'input[name=account]');
const telInput = editor.querySelector( 'input[name=tel]');
const emailInput = editor.querySelector( 'input[name=email]');
const passwordInput = editor.querySelector( 'input[name=password]');
const confirmInput = editor.querySelector( 'input[name=confirm]');
const button = editor.querySelector('button');

const list = $('.list');
const buttons = $('.buttons');

list.addEventListener('click', evt => {
    // 获得事件目标
    const t = evt.target;
    console.log( t );
    if( t.nodeName === 'A' ) {
        let { type , id } = t.dataset ;
        console.log( type , id );
        switch( type ) {
            case 'edit': 
                editUser(id) ; 
                break;
            case 'remove': 
                removeUser(id); 
                break;
        }
    }
}, true );

buttons.addEventListener('click' , evt => {
    // 阻止事件默认行为
    evt.preventDefault();
    // 阻止事件传播
    evt.stopPropagation(); 
    // 获得事件目标(即发生点击事件的元素)
    const t = evt.target;
    if( t.nodeName === 'A' ) {
        // 获得 a 元素的 data-type 属性值
        switch( t.dataset.type ){
            case 'add': 
                showEditor();
                break;
            case 'refresh': 
                loadAllUser(); // 重新加载用户列表即为刷新用户列表
                break;
        }
    }
    
} , true );

// 显示编辑区域
const showEditor = user =>{
    // 让 editor 区域显示
    editor.style.display = 'flex';

    // 如果参数user存在则表示属于编辑操作
    if( user ) {
        button.innerHTML = '修改';
        button.addEventListener( 'click' , modifyUser , false );
        return;
    }
    // 若参数user不存在则视为添加操作
    button.innerHTML = '添加';
    button.addEventListener( 'click' , addUser , false );
}

// 隐藏编辑区域
const hideEditor = () => {
    // 隐藏整个编辑区域
    editor.style.display = 'none' ;    
    // 清空编辑区域的各个组件
    accountInput.value = '';
    telInput.value = '';
    emailInput.value = '';
    passwordInput.value = '';
    confirmInput.value = '';
    button.innerHTML = '';
    // 移除 button 上曾经绑定的监听器
    button.removeEventListener('click', addUser, false);
    button.removeEventListener('click', modifyUser, false);
    // 移除 editor 的 data-id 属性
    editor.removeAttribute( 'data-id' );
}

// 定义用来获取用户列表的函数
const loadAllUser = () => {

    // 注意，参数 evt 表示 readystatechange 事件
    let handler = (data,xhr) => {
        console.log( 'data: ' , typeof data );
        // 将 JSON 格式字符串 解析为 JavaScript 对象
        let result = JSON.parse( data );
        if( result.success ) {
            const users = result.users ;
            // 首先清空 list 区域
            list.innerHTML = '' ;
            // 遍历数组并将其中每个元素添加到 .list 内部
            users.forEach( u => {
                // 创建新的 div 元素
                let node = document.createElement('div');
                // 为 node 添加 class name
                node.classList.add( 'user' );

                node.innerHTML = `<span class="id">${u.id}</span>
                                  <span class="account">${u.account}</span>
                                  <span class="email">${u.email}</span>
                                  <span class="tel">${u.tel}</span>
                                  <span class="operation">
                                    <a data-type="edit" data-id="${u.id}">编辑</a>
                                    <a data-type="remove" data-id="${u.id}">删除</a>
                                  </span>`;

                list.appendChild( node );
            });
            return;
        }
        // 若查询失败则弹出失败原因
        alert( result.cause );
    }

    // 调用函数发送异步请求
    ajax( 'get' , '/user/list' , null , handler );
}

// 添加用户(将用户信息发送到服务端并获取服务端处理结果)
const addUser = ()=>{
    // 根据用户输入的数据创建一个JavaScript对象
    let user = {
        account: accountInput.value,
        tel: telInput.value,
        email: emailInput.value,
        password: passwordInput.value,
        confirm: confirmInput.value,
    }

    let success = (data,xhr)=>{
        let result = JSON.parse( data );
        if( result.success ) {
            alert( result.message );// 临时使用，将来强烈反对使用
            // 隐藏编辑区域
            hideEditor();
            // 重新加载用户列表
            loadAllUser();
            return;
        }
        alert( result.message );
    }

    // 发送异步请求并将 user 对象以 JSON 格式发送给服务器端
    ajax('post','/user/add' , JSON.stringify(user) , success , 'application/json' );
}

// 查询指定id的用户并将其显示到编辑区域中
const editUser = id => {
    ajax('get',`/user/find/${id}` , null , (data,xhr)=>{
        // 将服务端返回的JSON字符串解析为对象
        let x = JSON.parse(data);
        // 若 x 的 success 为 true 
        if( x.success ) {
            // 则调用 showEditor 并将 user 对象传递过去
            showEditor( x.user );
            initEditor( x.user );
        }
    });
}

// 为修改操作初始化编辑区域各个组件
const initEditor = user => {
    editor.setAttribute( 'data-id' , user.id );
    accountInput.value = user.account;
    telInput.value = user.tel;
    emailInput.value = user.email;
    passwordInput.value = user.password;
    confirmInput.value = user.password;
}

// 修改用户(将修改后的数据异步发送给后端并获取后端处理结果)
const modifyUser = () => {
    let user = {
        id: editor.dataset.id ,
        account: accountInput.value ,
        tel: telInput.value ,
        email: emailInput.value ,
        password: passwordInput.value ,
        confirm: confirmInput.value ,
    }

    let success = (data,xhr) => {
        let x = JSON.parse(data);
        if( x.success ) {
            alert( x.message );
            loadAllUser();
            return;
        }
        alert( x.message );
    }

    ajax('post','/user/modify' , JSON.stringify(user) , success , 'application/json');

    hideEditor();
}

// 删除用户
const removeUser = id => {
    ajax('get',`/user/remove/${id}` , null , (data,xhr) => {
        console.log( data , typeof data );
        let x = JSON.parse( data );
        console.log( x , typeof x );
        if( x.success ){
            alert( x.message );
            loadAllUser();
            return;
        }
        alert( x.message );
    });
}

// 直接调用 loadAllUser 获取所有用户
loadAllUser();